#include <boost/spirit/include/classic_core.hpp>
#include <boost/spirit/include/classic_push_back_actor.hpp>
#include <iostream>
#include <vector>
#include <string>
#include <fstream>

using namespace std;
using namespace boost::spirit::classic;

std::string get_config_spec(){
    ifstream ifs("cfg_CI_BF_B5");
    if (!ifs){
        cerr << "Can't open the file cfg_CI_BF_B5" << endl;
        exit(1);
    }
    string line, total;
    while(getline(ifs, line)){
        line += "\n";
        total += line;
    }
    return total;
}

void print_version(char const* first, char const* last)
{
    string version(first, last);
    cout << "The version is: " << version << std::endl;
}

void print_from_where(char const* first, char const* last)
{
    string where(first, last);
    cout << "from: " << where << std::endl;
}
void get_product(char const* first, char const* last)
{
    string product(first, last);
    cout << "The product is: " << product << std::endl;
}

void print_sc_name(const char* first, const char* last)
{
    string sc_name(first, last);
    cout << "The SC name is: " << sc_name << endl;
}

void print_sc_path(const char* first, const char* last)
{
    string sc_path(first, last);
    cout << "The SC version is: " << sc_path << endl;
}

void print_shared_baselines(const char* first, const char* last)
{
    cout << "SCs from shared: " << endl;
}

void print_dimension_baselines(const char* first, const char* last)
{
    cout << "SCs from dimensions: " << endl;
}

typedef rule<phrase_scanner_t> R;
struct ConfigGrammar: public grammar<ConfigGrammar>
{
    template <typename ScannerT> struct definition
    {
        R version_string, product_string, version, product;
        R where, sc_name, sc_version, sc_info;
        R node, config_spec_parser;
        definition(const ConfigGrammar& self){
            version_string = lexeme_d[str_p("LN") >> !str_p("T") >> *(alpha_p | digit_p | '_' |'.')];
            product_string = lexeme_d[*(alpha_p | digit_p | '_')];
    
            //config_spec grammer describtion
            version = str_p("version") >> version_string[&print_version];
            product = str_p("product") >> product_string[&get_product];
    
            where = lexeme_d[alpha_p >> *(alpha_p | digit_p | ':')];

            sc_name = lexeme_d[alpha_p >> *( (graph_p&(~str_p('<'))) | digit_p | '_' | '.' )];
            sc_version = lexeme_d[alpha_p >> *( (graph_p&(~str_p('<'))) | digit_p | '_' | '.' )];
    
            sc_info = sc_name[&print_sc_name]  >> sc_version[&print_sc_path];
        
            node = ch_p('<') >> str_p("baselines") >> str_p("from") >> where[&print_from_where] >> ch_p('>')
                             >> (*sc_info)
                             >> ch_p("<") >> ch_p('/') >>  str_p("baselines") >> ch_p(">");

            config_spec_parser = version >> product >> *node >> end_p;
            
        }
        rule<ScannerT> const& start()const{
            return config_spec_parser;
        }
    };
};

    
int main(){

    
    //parse the cofnig_spec
    cout << "Input: " << endl;
    cout << get_config_spec();
    cout << "Input ended." << endl << endl;
    ConfigGrammar cg;
    parse_info<const char*> pi = parse(get_config_spec().c_str(), cg, space_p);
    
    if (pi.full){
        cout << "Success" << endl;
    }
    else if(pi.hit){
        cout << "Partial sucess" << endl;
    }
    
    else{
        cout << "Fail at : #" << pi.stop << endl;
    }
    return 0;
}

                

// struct config : public grammer<calculator>
// {
//     template <typename ScannerT>
//     struct definition
//     {
//         definition(const config& self)
//         {
//         }
//         rule<ScannerT> from_share, from_dimension, config_spec;
//         rule<ScannerT> const& start(){
//             const(return config_spec);
//         }
//     };
// };
